import re
import os
import time

from metagpt.actions import Action, UserRequirement
from metagpt.const import MESSAGE_ROUTE_TO_NONE
from metagpt.logs import logger
from metagpt.roles import Role
from metagpt.schema import Message

from all_actions import *


old_arrays = []

def extract_result_deepseek(llm_resp: str) -> str:
    lines = llm_resp.split("\n")
    last_line = lines[-1]

    result = "True" in last_line
    if result:
        return "Correct"

    return "Wrong"


def extract_result_qwen(llm_resp: str) -> str:
    search_obj = re.search(r'\\boxed\{\\text\{(.*)\}\}', llm_resp, re.M | re.I)
    # print(f"group 1: {search_obj.group(1)}")
    result = eval(search_obj.group(1))
    if result:
        return "Correct"

    return "Wrong"


class DealCards(Action):
    PROMPT_TEMPLATE: str = """
    Generate 4 random natural numbers between 1 and 13, include 1 and 13. Just return 4 numbers in an array, don't include other content. The returned array should not be repeated with the following arrays:
    {old_arrays}
    """
    name: str = "DealCards"

    async def run(self, context: str):
        global old_arrays
        # old_arrays = get_old_point_arrays(context)
        print(f"used old_arrays is :{old_arrays}")
        
        prompt = self.PROMPT_TEMPLATE.format(old_arrays=old_arrays)
        rsp = await self._aask(prompt)
        old_arrays.append(eval(rsp))
        return f"{{\"point_list\": {rsp}}}"


class CheckExpression(Action):
    PROMPT_TEMPLATE: str = """
    Calculate the result of this conditional expression 'abs(({expression}) - 24) < 0.1'.
    Just return "True" or "False", don't return other content.
    """

    name: str = "CheckExpression"

    async def run(self, expression: str):
        if expression == "expression not found":
            return "Correct"
        
        prompt = self.PROMPT_TEMPLATE.format(expression=expression)
        rsp = await self._aask(prompt)
        used_lm_family = get_used_lm_family()
        if used_lm_family == "deepseek":
            check_result = extract_result_deepseek(rsp)
        else:
            check_result = extract_result_qwen(rsp)
        return check_result
    

class GameJudger(Role):
    name: str = "Peter"
    profile: str = "GameJudger"

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.set_actions([DealCards])
        self._watch([UserRequirement, RequireDealCardsAgain, HumanGiveExpression, MachineGiveExpression])

    
    async def _act(self) -> Message:
        context = self.get_memories()
        msg = self.get_memories(k=1)[0]
        cause_by_str = f"{msg.cause_by}"

        if ("UserRequirement" in cause_by_str) or ("RequireDealCardsAgain" in cause_by_str):
            await self.call_deal_cards(context)
        elif msg.content == "expression not found":
            await self.call_deal_cards(context)
        else:
            math_lm = get_math_lm()
            todo = CheckExpression(config=math_lm)
            check_result = await todo.run(msg.content)
            print(f"==== Your expression '{msg.content}' is {check_result}. ====")

            if check_result == "Correct":
                await self.call_deal_cards(context)
            else:
                self.rc.env.publish_message(Message(content=check_result, cause_by=WrongExpression))
            
        return Message(content="dummy message", send_to=MESSAGE_ROUTE_TO_NONE)
        

    async def call_deal_cards(self, context):
        todo = DealCards()
        card_content = await todo.run(context)
        self.rc.env.publish_message(Message(content=card_content, cause_by=DealCards))
